在一般的模型開發流程中,我們經歷過了Training、Testing之後。如果順利完成了一個不錯的模型,但那之後呢?今天要介紹的就是所謂的Serving,即模型佈署之道。
在先前諸多的實驗中,最後選用上一篇所訓練出來的L2的參數。經過驗證src/evaluate.py
以後可以得到下面的Testing結果:
Testing DataLoader 0: 100%|███████████████████████████████████████████████████████████████████████████████████| 44/44 [00:05<00:00, 7.58it/s]
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Test metric ┃ DataLoader 0 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ test/acc │ 0.9476282000541687 │
│ test/auroc │ 0.772826611995697 │
│ test/loss │ 0.16255274415016174 │
└───────────────────────────┴───────────────────────────┘
基本上結果已經跟MedMNIST網站內的BenchMark差不多囉!可以放心應該已經適合結束實驗的階段。
(一般Task的允收標準除了BenchMark以外、還可以參考High Performance之類的)
對於版本與框架錯綜複雜的深度學習,佈署長久以來一直是個很棘手的問題。 Open Neural Network Exchange又簡稱ONNX,是一個嘗試將深度學習的模型進行標準化的格式。基本上任何模型如果能轉成這個格式,在佈署上便可以省掉不少麻煩。接著就讓我們來進行模型的格式轉換吧!
基本上PyTorch與PyTorch-Lightning對於onnx已經有相當不錯的支援了,只要下列幾行就便可轉檔:
net = model.MultiLabelsModel.load_from_checkpoint(CONFIG['evaluate']['weights_path'])
net.to_onnx('model.onnx',
input_sample = torch.rand([1,3,28,28]),
export_params=True)
接著事前的準備便完成啦!
早期滿多實作都是架一個Flask API來作為serving的服務使用,使用上是容易上手,但其實裡頭使用Python來抓取模型、進行推論的主要媒介,其實對於記憶體跟運算速度都不是很有效率。
所謂站在巨人的肩膀上,這裡選用的是NVIDIA家出廠的Triton Inference Server來作為基礎Serving的服務,效能很不錯,不過東西很新,使用上很多小問題需要依靠社群的力量解決。也有不少家其他的Inference Server,例如TensorFlow Serving,不過我個人沒有用過,各位有興趣可以再嘗試看看。
具體的設定有點繁瑣,可以參考下列要點:
docker network create ithome_network
networks:
default:
external:
name: ithome_network
version: "3.7"
networks:
default:
external:
name: ithome_network
services:
triton:
container_name: "iThome2022_Triton"
image: nvcr.io/nvidia/tritonserver:22.08-py3
runtime: nvidia
shm_size: '32GB'
command:
- tritonserver
- --model-repository=/models
- --log-verbose=1
- --model-control-mode=explicit
- --load-model=chestmnist_net
volumes:
- ./deploy:/models
ports:
- 8000:8000
然後按下:
docker-compose -f docker-compose-triton.yml up
就可以開啟了,另外要注意的是開啟GPU模式時triton的版本跟本機的CUDA可能會有相容性問題,要稍微挑一下版本,由於個人用11.7所以選22.08。
以上都沒跳錯的話,一切就都設置完成囉!
那設定好API以後,就可以開始測試結果啦!只使用Python的朋友需要先裝一個triton開發的client可以進行測試:
pip install tritonclient[all]
接著可以利用這個工具,進行以下的post:
import tritonclient.grpc as grpcclient
import tritonclient.http as httpclient
def triton_run(processed_img, module_name, triton_api_path):
with httpclient.InferenceServerClient(triton_api_path) as client:
# initial inputs format
inputs = [
httpclient.InferInput("input", processed_img.shape, 'FP32')
]
outputs = [
httpclient.InferRequestedOutput("output"),
]
inputs[0].set_data_from_numpy(processed_img.numpy())
response = client.infer(module_name,
inputs,
model_version = '1',
request_id=str(1),
outputs=outputs)
result = response.get_response()
output = response.as_numpy("output")
return output
仔細的內容可以參考src/evaluate_with_triton.py,一樣可以執行:
# python src/evaluate_with_triton.py --config=hparams.yaml
100%|████████████████████████████████████████████████████████████████████████| 44/44 [00:04<00:00, 9.65it/s]
Inference Result : AUC = 0.7728351871517246
基本上結果大概在小數點四位內都與原生Pytorch的結果相同,看起來是個合理的模型佈署!